package com.example.nacos.cal;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class FundReturnsCalculator {

    public static FundReturnsResult calculateCumulativeReturns(List<FundData> fundDataList) {
        if (fundDataList == null || fundDataList.isEmpty()) {
            throw new IllegalArgumentException("基金数据列表不能为空");
        }

        // 按日期排序
        List<FundData> sortedData = fundDataList.stream()
                .sorted(Comparator.comparing(FundData::getStatDate))
                .collect(Collectors.toList());

        // 获取最新净值和最新日期
        FundData latestData = sortedData.get(sortedData.size() - 1);
        Double latestValue = latestData.getCumulativeNetValue();
        LocalDate latestDate = latestData.getStatDate();
        String fundCode = latestData.getFundCode();

        FundReturnsResult result = new FundReturnsResult(fundCode);

        // 计算各时间段的累计收益率
        calculatePeriodReturn(sortedData, latestValue, latestDate, result, "近一周", 7, ChronoUnit.DAYS);
        calculatePeriodReturn(sortedData, latestValue, latestDate, result, "近一月", 30, ChronoUnit.DAYS);
        calculatePeriodReturn(sortedData, latestValue, latestDate, result, "近三个月", 90, ChronoUnit.DAYS);
        calculatePeriodReturn(sortedData, latestValue, latestDate, result, "近半年", 180, ChronoUnit.DAYS);
        calculatePeriodReturn(sortedData, latestValue, latestDate, result, "近一年", 365, ChronoUnit.DAYS);
        calculateYearToDateReturn(sortedData, latestValue, latestDate, result);

        return result;
    }

    private static void calculatePeriodReturn(List<FundData> sortedData,
                                              Double latestValue,
                                              LocalDate latestDate,
                                              FundReturnsResult result,
                                              String periodName,
                                              int days,
                                              ChronoUnit unit) {
        LocalDate cutoffDate = latestDate.minus(days, unit);

        List<FundData> periodData = sortedData.stream()
                .filter(data -> !data.getStatDate().isBefore(cutoffDate))
                .collect(Collectors.toList());

        if (periodData.size() >= 2) {
            Double startValue = periodData.get(0).getCumulativeNetValue();
            if (startValue != null && startValue > 0) {
                Double periodReturn = (latestValue / startValue) - 1;
                result.addReturn(periodName, periodReturn);
            } else {
                result.addReturn(periodName, null);
            }
        } else {
            result.addReturn(periodName, null);
        }
    }

    private static void calculateYearToDateReturn(List<FundData> sortedData,
                                                  Double latestValue,
                                                  LocalDate latestDate,
                                                  FundReturnsResult result) {
        LocalDate yearStart = LocalDate.of(latestDate.getYear(), 1, 1);

        List<FundData> ytdData = sortedData.stream()
                .filter(data -> !data.getStatDate().isBefore(yearStart))
                .collect(Collectors.toList());

        if (ytdData.size() >= 2) {
            Double startValue = ytdData.get(0).getCumulativeNetValue();
            if (startValue != null && startValue > 0) {
                Double ytdReturn = (latestValue / startValue) - 1;
                result.addReturn("今年以来累计收益率", ytdReturn);
            } else {
                result.addReturn("今年以来累计收益率", null);
            }
        } else {
            result.addReturn("今年以来累计收益率", null);
        }
    }

    public static void main(String[] args) {

        String fileName = "D:\\python\\ind_cal\\净值数据.xlsx";
        List<FundData> fundDataList = new ArrayList<>();

        EasyExcel.read(fileName, FundData.class, new PageReadListener<FundData>(fundDataList::addAll)).sheet().doRead();
        if (fundDataList.isEmpty()) {
            System.out.println("没有数据");
            return;
        }

        log.info("一条为：{}", JSON.toJSONString(fundDataList.get(0)));
        log.info("数据总数为：{}", fundDataList.size());

        // 按照产品分组
        Map<String, List<FundData>> groupedData = fundDataList.stream()
                .collect(Collectors.groupingBy(FundData::getFundCode));

        for (Map.Entry<String, List<FundData>> entry : groupedData.entrySet()) {
            String fundCode = entry.getKey();
            List<FundData> fundDataListForFundCode = entry.getValue();
            FundReturnsResult result = calculateCumulativeReturns(fundDataListForFundCode);
            System.out.println("基金代码: " + result.getFundCode());
            System.out.println("收益率计算结果:");
            result.getReturns().forEach((period, returnValue) -> {
                if (returnValue != null) {
                    System.out.printf("%s: %.2f%%\n", period, returnValue * 100);
                } else {
                    System.out.printf("%s: 数据不足\n", period);
                }
            });
        }

//        try {
//            FundReturnsResult result = calculateCumulativeReturns(fundDataList);
//            System.out.println("基金代码: " + result.getFundCode());
//            System.out.println("收益率计算结果:");
//            result.getReturns().forEach((period, returnValue) -> {
//                if (returnValue != null) {
//                    System.out.printf("%s: %.2f%%\n", period, returnValue * 100);
//                } else {
//                    System.out.printf("%s: 数据不足\n", period);
//                }
//            });
//        } catch (Exception e) {
//            System.err.println("计算收益率时发生错误: " + e.getMessage());
//        }
    }
}